package hn.sigit.view;

import hn.sigit.logic.bpm.PropertyData;
import hn.sigit.model.hnd.cadastre.HND_Property;
import hn.sigit.dao.hnd.cadastre.HND_PropertyDAO;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.richfaces.model.DataProvider;
import org.richfaces.model.ExtendedTableDataModel;
import org.richfaces.model.selection.SimpleSelection;

@Name("selectPropertyHelper")
@Scope(value = ScopeType.CONVERSATION)
@AutoCreate
public class SelectPropertyHelper implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private List<HND_Property> properties;
	private HND_Property selectedProperty;
	private SimpleSelection propertySelection;
	private String propertyName;
	private List<HND_Property> selectedNaturalPersonParties = new ArrayList<HND_Property>();
	
	private String propertyIdField;
	private String propertyCodeField;
	private String propertyNameField;
	private String propertyTypeField;
	private String reRenderComponents;
	
	private boolean addToList = false;
	private String selectedPropertyDataField;
	private String addToListMethod;

	private ExtendedTableDataModel<HND_Property> dataModel;

	public List<HND_Property> getProperties() {
		if (properties == null) {
			properties = HND_PropertyDAO.loadProperties();
		}
		return properties;
	}

	public void setProperties(List<HND_Property> properties) {
		this.properties = properties;
	}

	public HND_Property getSelectedNaturalPerson() {
		return selectedProperty;
	}

	public void setSelectedNaturalPerson(HND_Property selectedProperty) {
		this.selectedProperty = selectedProperty;
	}

	public SimpleSelection getPropertySelection() {
		return propertySelection;
	}

	public void setPropertySelection(SimpleSelection propertySelection) {
		this.propertySelection = propertySelection;
	}

	public String getPropertyName() {
		return propertyName;
	}

	public void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}

	public List<HND_Property> getSelectedNaturalPersonParties() {
		return selectedNaturalPersonParties;
	}

	public void setSelectedNaturalPersonParties(
			List<HND_Property> selectedNaturalPersonParties) {
		this.selectedNaturalPersonParties = selectedNaturalPersonParties;
	}

	public String getPropertyIdField() {
		return propertyIdField;
	}

	public void setPropertyIdField(String propertyIdField) {
		this.propertyIdField = propertyIdField;
	}

	public String getPropertyCodeField() {
		return propertyCodeField;
	}

	public void setPropertyCodeField(String propertyCodeField) {
		this.propertyCodeField = propertyCodeField;
	}

	public String getPropertyNameField() {
		return propertyNameField;
	}

	public void setPropertyNameField(String propertyNameField) {
		this.propertyNameField = propertyNameField;
	}
	
	public String getPropertyTypeField() {
		return propertyTypeField;
	}

	public void setPropertyTypeField(String propertyTypeField) {
		this.propertyTypeField = propertyTypeField;
	}

	public boolean isAddToList() {
		return addToList;
	}

	public void setAddToList(boolean addToList) {
		this.addToList = addToList;
	}

	public String getSelectedPropertyDataField() {
		return selectedPropertyDataField;
	}

	public void setSelectedPropertyDataField(String selectedPropertyDataField) {
		this.selectedPropertyDataField = selectedPropertyDataField;
	}

	public String getAddToListMethod() {
		return addToListMethod;
	}

	public void setAddToListMethod(String addToListMethod) {
		this.addToListMethod = addToListMethod;
	}

	public String getReRenderComponents() {
		return reRenderComponents;
	}

	public void setReRenderComponents(String reRenderComponents) {
		this.reRenderComponents = reRenderComponents;
	}

	public ExtendedTableDataModel<HND_Property> getDataModel() {
		if (dataModel == null) {
			dataModel = new ExtendedTableDataModel<HND_Property>(new DataProvider<HND_Property>() {
 
				private static final long serialVersionUID = 5054087821033164847L;

				public int getRowCount() {
					return getProperties().size();
				}
				public List<HND_Property> getItemsByRange(int firstRow, int endRow) {
					//TODO: Check if fetching from DB is better for memory usage
					return getProperties().subList(firstRow, endRow);
				}

				public HND_Property getItemByKey(Object key) {
					//TODO: Eliminar busqueda lineal
					for (HND_Property npp : getProperties())
						if (key.equals(getKey(npp)))
							return npp;

					return null;
				}
 
 				public Object getKey(HND_Property item) {
					return item.getuID();
				}
			});
 		}
		return dataModel;
	}

	public void takeSelection(ActionEvent ae) {
		getSelectedNaturalPersonParties().clear();
		Iterator<Object> iterator = getPropertySelection().getKeys();
		while (iterator.hasNext()){
			Object key = iterator.next();
			selectedProperty = getDataModel().getObjectByKey(key);
			//getSelectedNaturalPersonParties().add(getNaturalPersonPartiesDataModel().getObjectByKey(key));
			if (selectedProperty != null) {
				propertyName = "LOREM IPSUM: " + selectedProperty.getName();
				
				Application app = FacesContext.getCurrentInstance().getApplication();
				ExpressionFactory exprFactory = app.getExpressionFactory();
				ELContext elCtx = FacesContext.getCurrentInstance().getELContext();
				
				ValueExpression ve;
				if (!addToList) {
					if (propertyIdField != null) {
						ve = exprFactory.createValueExpression(elCtx, "#{" + propertyIdField + "}", String.class);
						ve.setValue(elCtx, String.valueOf(selectedProperty.getuID()));
					}
					if (propertyCodeField != null) {
						//TODO: Ver si la ficha de campo se usara siempre como el codigo
						ve = exprFactory.createValueExpression(elCtx, "#{" + propertyCodeField + "}", String.class);
						ve.setValue(elCtx, String.valueOf(selectedProperty.getName()));
					}
					if (propertyNameField != null) {
						ve = exprFactory.createValueExpression(elCtx, "#{" + propertyNameField + "}", String.class);
						ve.setValue(elCtx, propertyName);
					}
					if (propertyTypeField != null) {
						ve = exprFactory.createValueExpression(elCtx, "#{" + propertyTypeField + "}", String.class);
						ve.setValue(elCtx, selectedProperty.getType().toString());
					}
				}
				else {
					//adding to a list
					MethodExpression me;
					
					if (selectedPropertyDataField != null && addToListMethod != null) {
						PropertyData pd = new PropertyData();
						pd.setBaUnitID(selectedProperty.getuID());
						pd.setPropertyCode(String.valueOf(selectedProperty.getName()));
						pd.setName("LOREM IPSUM: " + selectedProperty.getName());
						pd.setType(selectedProperty.getType());
						
						ve = exprFactory.createValueExpression(elCtx, "#{" + selectedPropertyDataField + "}", PropertyData.class);
						ve.setValue(elCtx, pd);
						
						//third parameter is set to null meaning that we do not care for the
						//result type... and no expected parameters for fourth parameter,
						//however we can not use null for this argument
						me = exprFactory.createMethodExpression(elCtx, "#{" + addToListMethod + "}", null, new Class[] {});
						me.invoke(elCtx, null);
					}
				}
			}
		}
	}

}
